package com.tbit.main.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import com.tbit.main.common.JsonResult;
import com.tbit.main.constant.AccountDayStatConstant;
import com.tbit.main.dao.stat.AccountDayStatDao;
import com.tbit.main.pojo.AccountDataMain;
import com.tbit.main.pojo.AccountDayStat;
import com.tbit.main.pojo.AccountDayUM;
import com.tbit.main.pojo.VO.AccountDataMainVO;
import com.tbit.main.service.AccountDayStatService;
import com.tbit.main.service.manager.util.DateUtils;
import com.tbit.main.util.DateTimeUtil;
import com.tbit.main.util.LogUtil;
import com.tbit.main.util.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author LMY
 * @create 2022-11-09 16:27
 */
@Service
public class AccountDayStatServiceImpl implements AccountDayStatService {

    @Autowired
    private AccountDayStatDao accountDayStatDao;

    @Override
    public List<AccountDayStat> getBrandIdAccountIdType(Integer brandId, String accountIds, String startTime, String endTime) {
        Map<String, Object> map = new HashMap<>();
        map.put("brandId", brandId);
        map.put("accountId", accountIds);
        map.put("startTime", DateTimeUtil.getYYMMDDInteger(startTime));
        map.put("endTime", DateTimeUtil.getYYMMDDInteger(endTime));
        return accountDayStatDao.getBrandIdAccountIdType(map);
    }

    @Override
    public JsonResult<List<AccountDataMainVO>> groupMachineByDay(Integer brandId, String accountIds, String startTime, String endTime) {
        List<String> dateList = DateUtils.getMonthBetweenDate(startTime, endTime, "yyyy-MM-dd", Calendar.DAY_OF_MONTH);
        List<AccountDataMainVO> resultList = dateList.stream().map(x -> {
            AccountDataMain dataMain = getMachine(brandId, accountIds, x + " 00:00:00", x + " 23:59:59");
            if (dataMain == null) {
                dataMain = new AccountDataMain();
            }
            dataMain.nullValueSetDefaultVal();
            return new AccountDataMainVO(x, dataMain);
        }).collect(Collectors.toList());
        return JsonResult.succ(resultList);
    }

    @Override
    public AccountDataMain getMachine(Integer brandId, String accountIds, String startTime, String endTime) {

        Map<String, Object> map = new HashMap<>(8);
        map.put("brandId", brandId);
        map.put("accountId", accountIds);
        map.put("startTime", DateUtil.format(DateTimeUtil.StringToDateTime(startTime), "yyyyMMdd"));
        map.put("endTime", DateUtil.format(DateTimeUtil.StringToDateTime(endTime), "yyyyMMdd"));
        Map<Integer, AccountDayStat> accountDayStatMap = accountDayStatDao.getBrandIdAccountIdTypeSum(map)
                .stream()
                .collect(Collectors.toMap(AccountDayStat::getDataType, x -> x));
        AccountDayStatConstant.getAoperationAndMaintenance_Data()
                .forEach(x -> {
                    if (accountDayStatMap.get(x) == null) {
                        accountDayStatMap.put(x, new AccountDayStat(null, null, null, null, null, null, null, null, null, 0L, 0L, null, null, null, null, null));
                    }
                });
        //查最后一天的数据
        map.put("startTime", DateUtil.format(DateTimeUtil.StringToDateTime(endTime), "yyyyMMdd"));
        Map<Integer, AccountDayStat> dayStatMap = accountDayStatDao.getBrandIdAccountIdTypeSum(map)
                .stream()
                .collect(Collectors.toMap(AccountDayStat::getDataType, x -> x));
        //填充数据
        AccountDataMain accountDataMain = new AccountDataMain()
                .setMachineSum(nullToZero(dayStatMap.get(AccountDayStatConstant.TOTAL_NUMBER_OF_VEHICLES)))
                .setMachineLaunch(nullToZero(dayStatMap.get(AccountDayStatConstant.NUMBER_OF_VEHICLES_LAUNCHED)))
                .setMachineRun(nullToZero(dayStatMap.get(AccountDayStatConstant.NUMBER_OF_OPERATIONAL_VEHICLES)))
                .setMachineKM(accountDayStatMap.get(AccountDayStatConstant.NUMBER_OF_NEW_MILEAGE).getSumTotal() / 1000)
                .setAccountUserSum(accountDayStatMap.get(AccountDayStatConstant.NUMBER_OF_MAIN_USER).getSumTotal())
                .setPowerSum(accountDayStatMap.get(AccountDayStatConstant.NUMBER_OF_POWER_CHANGES).getSumTotal())
                .setMoveSum(accountDayStatMap.get(AccountDayStatConstant.NUMBER_OF_MOVES).getSumTotal())
                .setDispatchSum(accountDayStatMap.get(AccountDayStatConstant.NUMBER_OF_DISPATCHES).getSumTotal())
                .setUserSum(nullToZero(dayStatMap.get(AccountDayStatConstant.CUMULATIVE_NUMBER_OF_USERS)))
                .setUserNewSum(accountDayStatMap.get(AccountDayStatConstant.NUMBER_OF_NEW_USERS).getSumTotal())
                .setDailyRidingUser(Optional.ofNullable(accountDayStatMap.get(AccountDayStatConstant.DAILY_RIDING_USER)).map(AccountDayStat::getSumTotal).orElse(0L))
                .setPatrolSum(Optional.ofNullable(accountDayStatMap.get(AccountDayStatConstant.NUMBER_OF_PATROL)).map(AccountDayStat::getSumTotal).orElse(0L))
                .setRepairSum(Optional.ofNullable(accountDayStatMap.get(AccountDayStatConstant.NUMBER_OF_REPAIR)).map(AccountDayStat::getSumTotal).orElse(0L))
                .setMachineOutRange(Optional.ofNullable(accountDayStatMap.get(AccountDayStatConstant.MACHINE_NUMBER_OF_OUT_RANGE)).map(AccountDayStat::getSumTotal).orElse(0L))
                .setMachineFeed(Optional.ofNullable(accountDayStatMap.get(AccountDayStatConstant.THE_NUMBER_OF_TROLLEY_CARS_IS_SHORT)).map(AccountDayStat::getSumTotal).orElse(0L))
                .setMachineOutSide(Optional.ofNullable(accountDayStatMap.get(AccountDayStatConstant.MACHINE_NUMBER_OF_OUT_SIDE)).map(AccountDayStat::getSumTotal).orElse(0L))
                .setMachineNoSignal(Optional.ofNullable(accountDayStatMap.get(AccountDayStatConstant.MACHINE_NUMBER_OF_NO_SIGNAL)).map(AccountDayStat::getSumTotal).orElse(0L))
                .setMachineFree(Optional.ofNullable(accountDayStatMap.get(AccountDayStatConstant.MACHINE_NUMBER_OF_FREE)).map(AccountDayStat::getSumTotal).orElse(0L))
                .setNeatSum(Optional.ofNullable(accountDayStatMap.get(AccountDayStatConstant.NUMBER_OF_NEAT)).map(AccountDayStat::getSumTotal).orElse(0L))
                .setMachineFault(Optional.ofNullable(accountDayStatMap.get(AccountDayStatConstant.NUMBER_OF_BROKEN_DOWN_VEHICLES)).map(AccountDayStat::getSumTotal).orElse(0L))
                .setRideIncome(Optional.ofNullable(accountDayStatMap.get(AccountDayStatConstant.CYCLING_INCOME)).map(AccountDayStat::getSumTotal).map(x -> x == 0 ? 0.0D : (double) x / 100).orElse(0d));
        accountDataMain.setAccountArea(accountDataMain.area(accountDayStatMap.get(AccountDayStatConstant.NUMBER_OF_AREA).getSumTotal()));
        accountDataMain.compute();
        accountDataMain.carbon(Optional.ofNullable(accountDayStatMap.get(AccountDayStatConstant.REDUCE_EMISSIONS)).map(AccountDayStat::getSumTotal).orElse(0L));
        accountDataMain.density();
        accountDataMain.setPowerAccountUser(calculateMainAvg(accountDayStatMap.get(AccountDayStatConstant.NUMBER_OF_POWER_CHANGES)));
        accountDataMain.setMoveAccountUser(calculateMainAvg(accountDayStatMap.get(AccountDayStatConstant.NUMBER_OF_MOVES)));
        accountDataMain.setDispatchAccountUser(calculateMainAvg(accountDayStatMap.get(AccountDayStatConstant.NUMBER_OF_DISPATCHES)));
        long moneyIncome = (accountDayStatMap.get(AccountDayStatConstant.CYCLING_INCOME).getSumTotal() + accountDayStatMap.get(AccountDayStatConstant.USER_FINE_INCOME).getSumTotal());
        //车均收入、车均订单：日均数据
        accountDataMain.calculateMachineOrderAvg(accountDayStatMap.get(AccountDayStatConstant.CYCLING_INCOME).getCntTotal());
        accountDataMain.calculateMachineMoneyAvg(moneyIncome);
        return accountDataMain;
    }

    public float calculateMainAvg(AccountDayStat accountDayStat) {
        if (accountDayStat == null || accountDayStat.getSumTotal() == null || accountDayStat.getSumTotal() <= 0 ||
                accountDayStat.getCntTotal() == null || accountDayStat.getCntTotal() <= 0) {
            return 0.0f;
        }
        return NumberUtil.div(accountDayStat.getSumTotal(), accountDayStat.getCntTotal(), 2).floatValue();
    }

    private long nullToZero(AccountDayStat accountDayStat) {
        return accountDayStat == null ? 0L : accountDayStat.getSumTotal();
    }

    @Override
    public AccountDayUM getByAccountIdUM(Integer brandId, String startTime, String endTime) {
        /**
         * 计算时间，获取数据
         */
        LogUtil.info("友盟：brandId:" + brandId + ",startTime:" + startTime + ",endTime:" + endTime);
        Integer start = DateTimeUtil.getNowDateBefore(endTime, -30);
        Integer week = DateTimeUtil.getNowDateBefore(endTime, -6);
        Integer end = DateTimeUtil.getNowDateBefore(endTime, 0);
        Map<String, Object> map = new HashMap<>();
        map.put("brandId", brandId);
        map.put("startTime", start);
        map.put("endTime", end);
        List<AccountDayStat> accountDayStats = accountDayStatDao.getBrandIdType(map);
        /**拼接数据*/
        Map<Integer, List<AccountDayStat>> dataMap = new HashMap<>();
        for (AccountDayStat accountDayStat : accountDayStats) {
            if (dataMap.containsKey(accountDayStat.getDataDate())) {
                dataMap.get(accountDayStat.getDataDate()).add(accountDayStat);
            } else {
                List<AccountDayStat> accountDayStats1 = new LinkedList<>();
                accountDayStats1.add(accountDayStat);
                dataMap.put(accountDayStat.getDataDate(), accountDayStats1);
            }
        }
        AccountDayUM accountDayUM = new AccountDayUM(0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L);
        for (Integer key : dataMap.keySet()) {
            /**月数据*/
            if (start <= key && key <= end) {
                for (AccountDayStat accountDayStat : dataMap.get(key)) {
                    switch (accountDayStat.getDataType()) {
                        //新增
                        case AccountDayStatConstant.NUMBER_UM_NEW_USER:
                            accountDayUM.setNewUserMonth(accountDayUM.getNewUserMonth() + accountDayStat.getSumTotal());
                            break;
                        //打开
                        case AccountDayStatConstant.NUMBER_UM_OPEN:
                            accountDayUM.setLaunchMonth(accountDayUM.getLaunchMonth() + accountDayStat.getSumTotal());
                            break;
                        //访问
                        case AccountDayStatConstant.NUMBER_UM_SLEEP:
                            accountDayUM.setVisitTimesMonth(accountDayUM.getVisitTimesMonth() + accountDayStat.getSumTotal());
                            break;
                    }
                }
            }
            /**周数据*/
            if (week <= key && key <= end) {
                for (AccountDayStat accountDayStat : dataMap.get(key)) {
                    switch (accountDayStat.getDataType()) {
                        //新增
                        case AccountDayStatConstant.NUMBER_UM_NEW_USER:
                            accountDayUM.setNewUserWeek(accountDayUM.getNewUserWeek() + accountDayStat.getSumTotal());
                            break;
                        //打开
                        case AccountDayStatConstant.NUMBER_UM_OPEN:
                            accountDayUM.setLaunchWeek(accountDayUM.getLaunchWeek() + accountDayStat.getSumTotal());
                            break;
                        //访问
                        case AccountDayStatConstant.NUMBER_UM_SLEEP:
                            accountDayUM.setVisitTimesWeek(accountDayUM.getVisitTimesWeek() + accountDayStat.getSumTotal());
                            break;
                    }
                }
            }
            /**天数据*/
            if (key.equals(end)) {
                for (AccountDayStat accountDayStat : dataMap.get(key)) {
                    switch (accountDayStat.getDataType()) {
                        //新增
                        case AccountDayStatConstant.NUMBER_UM_NEW_USER:
                            accountDayUM.setNewUser(accountDayStat.getSumTotal());
                            break;
                        //打开
                        case AccountDayStatConstant.NUMBER_UM_OPEN:
                            accountDayUM.setLaunch(accountDayStat.getSumTotal());
                            break;
                        //访问
                        case AccountDayStatConstant.NUMBER_UM_SLEEP:
                            accountDayUM.setVisitTimes(accountDayStat.getSumTotal());
                            break;
                    }
                }
            }

        }
        return accountDayUM;
    }

    @Override
    public List<AccountDayStat> getAccountIdsTypeDate(List<Integer> accountIds, Integer dataType, String startTime, String endTime) {
        Map<String, Object> map = new HashMap<>();
        map.put("accountIds", StringUtil.getListString(accountIds));
        map.put("startTime", DateTimeUtil.getYYMMDDInteger(startTime));
        map.put("endTime", DateTimeUtil.getYYMMDDInteger(endTime));
        map.put("dataType", dataType);
        return accountDayStatDao.getAccountIdsTypeDate(map);
    }

}
